package org.jeecg.modules.oms.parser.impl.confirmation;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.oms.entity.ProductSalesOrderDetail;
import org.jeecg.modules.oms.parser.WindowConfirmationFileParser;
import org.jeecg.modules.system.mapper.SysEmployeeMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.CompletableFuture;

// 引入JSON处理依赖
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.SpringContextUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * 长风优化软件窗型确认文件解析器
 * 专门用于解析长风优化软件导出的窗型确认文件
 */
@Component
public class ChangFengWindowConfirmationFileParser implements WindowConfirmationFileParser {

    // 窗型信息分割关键字
    private static final String[] WINDOW_DIVIDER_KEYWORDS = {"/", "页"};
    
    @Value("${jeecg.path.upload}")
    private String uploadPath;
    
    // 线程池配置
    private static final int MAX_THREADS = Runtime.getRuntime().availableProcessors() * 2;

    @Autowired
    private SysEmployeeMapper employeeMapper;

    @Lazy
    @Resource
    private RedisUtil redisUtil;
    
    /**
     * 解析长风优化软件的窗型确认文件
     *
     * @param file Excel文件
     * @param tenantId 租户ID
     * @return 产品销售订单明细列表
     * @throws IOException 文件读取异常
     * @throws Exception   其他解析异常
     */
    @Override
    public List<ProductSalesOrderDetail> parseFile(File file, Integer tenantId) throws IOException, Exception {
        List<ProductSalesOrderDetail> detailList = new ArrayList<>();
        
        try (InputStream is = new FileInputStream(file)) {
            Workbook workbook;
            
            // 根据文件后缀选择不同的Workbook实现
            if (file.getName().toLowerCase().endsWith(".xlsx")) {
                workbook = new XSSFWorkbook(is);
            } else if (file.getName().toLowerCase().endsWith(".xls")) {
                workbook = new HSSFWorkbook(is);
            } else {
                throw new IllegalArgumentException("不支持的文件格式，仅支持.xlsx和.xls格式");
            }
            
            // 调试：分析Excel文件中的图片信息
            analyzeExcelImages(workbook);
            
            // 创建线程池，线程数为处理器核心数的2倍
            int processors = Runtime.getRuntime().availableProcessors();
            ExecutorService executor = Executors.newFixedThreadPool(processors * 2);
            List<Future<List<ProductSalesOrderDetail>>> futures = new ArrayList<>();
            
            // 先遍历所有工作表，将窗型信息分割为多个任务
            for (int sheetIndex = 0; sheetIndex < workbook.getNumberOfSheets(); sheetIndex++) {
                Sheet sheet = workbook.getSheetAt(sheetIndex);
                if (sheet == null) {
                    continue;
                }
                
                // 分割sheet中的窗型信息，每个窗型作为一个独立任务
                List<WindowSection> windowSections = divideSheetIntoWindowSections(sheet);
                
                // 为每个窗型创建一个解析任务并提交到线程池
                for (WindowSection section : windowSections) {
                    Future<List<ProductSalesOrderDetail>> future = executor.submit(
                        new WindowSectionParseTask(sheet, section, workbook, tenantId)
                    );
                    futures.add(future);
                }
            }
            
            // 收集所有任务的结果
            for (Future<List<ProductSalesOrderDetail>> future : futures) {
                try {
                    List<ProductSalesOrderDetail> result = future.get();
                    if (result != null) {
                        detailList.addAll(result);
                    }
                } catch (Exception e) {
                    // 记录异常但继续处理其他任务
                    e.printStackTrace();
                }
            }
            
            // 关闭线程池
            executor.shutdown();
            try {
                if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
                    executor.shutdownNow();
                }
            } catch (InterruptedException e) {
                executor.shutdownNow();
                Thread.currentThread().interrupt();
            }
            
            workbook.close();
        }
        
        return detailList;
    }
    
    /**
     * 分析Excel文件中的图片信息
     * 
     * @param workbook 工作簿
     */
    private void analyzeExcelImages(Workbook workbook) {
        System.out.println("\n======= 开始分析Excel文件中的图片信息 =======");
        
        // 获取工作簿中的所有图片
        List<? extends PictureData> allPictures = workbook.getAllPictures();
        System.out.println("工作簿中共有 " + allPictures.size() + " 张图片");
        
        // 分析每张图片的格式和大小
        for (int i = 0; i < allPictures.size(); i++) {
            PictureData picture = allPictures.get(i);
            byte[] data = picture.getData();
            
            // 获取图片类型
            int pictureType = picture.getPictureType();
            String formatName = "";
            switch (pictureType) {
                case Workbook.PICTURE_TYPE_EMF: formatName = "EMF"; break;
                case Workbook.PICTURE_TYPE_WMF: formatName = "WMF"; break;
                case Workbook.PICTURE_TYPE_PICT: formatName = "PICT"; break;
                case Workbook.PICTURE_TYPE_JPEG: formatName = "JPEG"; break;
                case Workbook.PICTURE_TYPE_PNG: formatName = "PNG"; break;
                case Workbook.PICTURE_TYPE_DIB: formatName = "DIB"; break;
                default: formatName = "Unknown";
            }
            
            System.out.println("图片 " + (i+1) + ": 格式=" + formatName + ", 大小=" + data.length + " 字节");
        }
        
        // 分析每个工作表中的图片位置
        for (int sheetIndex = 0; sheetIndex < workbook.getNumberOfSheets(); sheetIndex++) {
            Sheet sheet = workbook.getSheetAt(sheetIndex);
            if (sheet == null) {
                continue;
            }
            
            System.out.println("\n工作表 " + (sheetIndex+1) + " (" + sheet.getSheetName() + "):");
            
            // 获取工作表中的所有绘图对象
            Drawing<?> drawing = sheet.getDrawingPatriarch();
            if (drawing != null) {
                int pictureCount = 0;
                
                // 遍历所有图片
                for (org.apache.poi.ss.usermodel.Shape shape : drawing) {
                    if (shape instanceof org.apache.poi.ss.usermodel.Picture) {
                        pictureCount++;
                        org.apache.poi.ss.usermodel.Picture pic = (org.apache.poi.ss.usermodel.Picture) shape;
                        org.apache.poi.ss.usermodel.ClientAnchor anchor = pic.getClientAnchor();
                        
                        if (anchor != null) {
                            System.out.println("  图片 " + pictureCount + " 位置: 行" + anchor.getRow1() + "-" + anchor.getRow2() + 
                                             ", 列" + anchor.getCol1() + "-" + anchor.getCol2());
                            
                            // 尝试获取图片所在单元格的内容
                            try {
                                Row row = sheet.getRow(anchor.getRow1());
                                if (row != null) {
                                    Cell cell = row.getCell(anchor.getCol1());
                                    if (cell != null) {
                                        String cellValue = getCellValueAsString(cell);
                                        System.out.println("    单元格内容: " + cellValue);
                                    }
                                }
                            } catch (Exception e) {
                                System.out.println("    无法获取单元格内容: " + e.getMessage());
                            }
                        }
                    }
                }
                
                System.out.println("  工作表中共有 " + pictureCount + " 个图片");
            } else {
                System.out.println("  工作表中不存在绘图对象");
            }
            
            // 分析窗型区域
            List<WindowSection> windowSections = divideSheetIntoWindowSections(sheet);
            System.out.println("  工作表中共有 " + windowSections.size() + " 个窗型区域");
            for (int i = 0; i < windowSections.size(); i++) {
                WindowSection section = windowSections.get(i);
                System.out.println("  窗型区域 " + (i+1) + ": 行" + section.getStartRow() + "-" + section.getEndRow());
                
                // 尝试提取窗号
                try {
                    Map<String, String> windowInfo = extractWindowInfo(sheet, section);
                    String windowNo = windowInfo.get("windowNo");
                    System.out.println("    窗号: " + (windowNo != null ? windowNo : "未找到"));
                } catch (Exception e) {
                    System.out.println("    无法提取窗号: " + e.getMessage());
                }
            }
        }
        
        System.out.println("======= Excel文件图片分析完成 =======\n");
    }
    
    /**
     * 窗型区域信息类，用于存储窗型的起始和结束行
     */
    private static class WindowSection {
        private final int startRow;
        private final int endRow;
        
        public WindowSection(int startRow, int endRow) {
            this.startRow = startRow;
            this.endRow = endRow;
        }
        
        public int getStartRow() {
            return startRow;
        }
        
        public int getEndRow() {
            return endRow;
        }
    }
    
    /**
     * 将工作表分割为多个窗型区域
     *
     * @param sheet 工作表
     * @return 窗型区域列表
     */
    private List<WindowSection> divideSheetIntoWindowSections(Sheet sheet) {
        List<WindowSection> sections = new ArrayList<>();
        
        int windowStartRow = -1;
        boolean isProcessingWindow = false;
        
        // 遍历每一行，查找窗型开始和结束标记
        for (int rowIndex = 0; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
            Row row = sheet.getRow(rowIndex);
            if (row == null) {
                continue;
            }
            
            // 检查是否是窗型开始行（第一列为"门窗内视立面图"，第四列为"门窗系列"）
            if (isWindowStartRow(row)) {
                // 如果正在处理窗型，则结束上一个窗型
                if (isProcessingWindow && windowStartRow >= 0) {
                    int windowEndRow = rowIndex - 1;
                    // 添加窗型区域
                    sections.add(new WindowSection(windowStartRow, windowEndRow));
                }
                // 开始新的窗型处理
                windowStartRow = rowIndex;
                isProcessingWindow = true;
                
                // 记录日志
                System.out.println("找到窗型开始行: " + rowIndex);
            }
            // 检查是否是窗型结束行（第一列包含"/"或"页"）
            else if (isWindowDividerRow(row) && isProcessingWindow) {
                int windowEndRow = rowIndex;
                // 添加窗型区域
                sections.add(new WindowSection(windowStartRow, windowEndRow));
                isProcessingWindow = false;
                windowStartRow = -1;
                
                // 记录日志
                System.out.println("找到窗型结束行: " + rowIndex);
            }
        }
        
        // 处理最后一个窗型
        if (isProcessingWindow && windowStartRow >= 0) {
            sections.add(new WindowSection(windowStartRow, sheet.getLastRowNum()));
            System.out.println("添加最后一个窗型区域: " + windowStartRow + " - " + sheet.getLastRowNum());
        }
        
        // 记录找到的窗型区域数量
        System.out.println("共找到 " + sections.size() + " 个窗型区域");
        for (int i = 0; i < sections.size(); i++) {
            WindowSection section = sections.get(i);
            System.out.println("窗型区域 " + (i+1) + ": " + section.getStartRow() + " - " + section.getEndRow());
        }
        
        return sections;
    }
    
    /**
     * 判断是否是窗型开始行
     * 第一列为"门窗内视立面图"，第四列为"门窗系列"
     *
     * @param row 行
     * @return 是否是窗型开始行
     */
    private boolean isWindowStartRow(Row row) {
        if (row == null || row.getLastCellNum() < 4) {
            return false;
        }
        
        Cell firstCell = row.getCell(0);
        Cell fourthCell = row.getCell(3);
        
        if (firstCell == null || fourthCell == null) {
            return false;
        }
        
        String firstCellValue = getCellValueAsString(firstCell);
        String fourthCellValue = getCellValueAsString(fourthCell);
        
        return firstCellValue.contains("门窗内视立面图") && fourthCellValue.contains("门窗系列");
    }
    
    /**
     * 窗型区域解析任务
     */
    private class WindowSectionParseTask implements Callable<List<ProductSalesOrderDetail>> {
        private final Sheet sheet;
        private final WindowSection section;
        private final Workbook workbook;
        private final Integer tenantId;
        
        public WindowSectionParseTask(Sheet sheet, WindowSection section, Workbook workbook, Integer tenantId) {
            this.sheet = sheet;
            this.section = section;
            this.workbook = workbook;
            this.tenantId = tenantId;
        }
        
        @Override
        public List<ProductSalesOrderDetail> call() throws Exception {
            List<ProductSalesOrderDetail> results = new ArrayList<>();
            
            try {
                // 提取窗型基本信息
                Map<String, String> windowInfo = extractWindowInfo(sheet, section);
                
                // 解析表格数据
                Map<String, JSONArray> tableDataMap = extractTableData(sheet, section);
                
                // 处理窗型信息
                ProductSalesOrderDetail detail = createProductDetail(windowInfo, tableDataMap, sheet, section, workbook, tenantId);
                if (detail != null) {
                    results.add(detail);
                }
            } catch (Exception e) {
                // 记录异常但不中断处理
                e.printStackTrace();
            }
            
            return results;
        }
    }
    
    /**
     * 从窗型区域提取窗型基本信息
     *
     * @param sheet 工作表
     * @param section 窗型区域
     * @return 窗型基本信息
     */
    private Map<String, String> extractWindowInfo(Sheet sheet, WindowSection section) {
        Map<String, String> windowInfo = new HashMap<>();
        
        // 遍历窗型区域的每一行
        for (int rowIndex = section.getStartRow(); rowIndex <= section.getEndRow(); rowIndex++) {
            Row row = sheet.getRow(rowIndex);
            if (row == null) {
                continue;
            }
            
            // 提取关键信息
            extractKeyInfo(row, windowInfo);
        }
        
        return windowInfo;
    }
    
    /**
     * 从窗型区域提取表格数据
     *
     * @param sheet 工作表
     * @param section 窗型区域
     * @return 表格数据映射
     */
    private Map<String, JSONArray> extractTableData(Sheet sheet, WindowSection section) {
        Map<String, JSONArray> tableDataMap = new HashMap<>();
        
        // 遍历窗型区域的每一行
        for (int rowIndex = section.getStartRow(); rowIndex <= section.getEndRow(); rowIndex++) {
            Row row = sheet.getRow(rowIndex);
            if (row == null) {
                continue;
            }
            
            // 遍历行中的所有单元格，查找表格标题
            for (int cellIndex = 0; cellIndex < row.getLastCellNum(); cellIndex++) {
                Cell cell = row.getCell(cellIndex);
                if (cell == null) {
                    continue;
                }
                
                String cellValue = getCellValueAsString(cell);
                if (cellValue.isEmpty()) {
                    continue;
                }
                
                // 检查是否是型材尺寸表标题行
                if (cellValue.contains("型材尺寸表")) {
                    JSONArray profileSizeTable = parseProfileSizeTable(sheet, rowIndex, cellIndex);
                    if (profileSizeTable != null && !profileSizeTable.isEmpty()) {
                        tableDataMap.put("profileSizeTable", profileSizeTable);
                    }
                    // 找到表格后跳出当前行的循环，避免重复处理
                    break;
                }
                
                // 检查是否是玻璃尺寸表标题行
                else if (cellValue.contains("玻 璃 尺 寸 表")) {
                    JSONArray glassSizeTable = parseGlassSizeTable(sheet, rowIndex, cellIndex);
                    if (glassSizeTable != null && !glassSizeTable.isEmpty()) {
                        tableDataMap.put("glassSizeTable", glassSizeTable);
                    }
                    break;
                }
                
                // 检查是否是配件表标题行
                else if (cellValue.contains("配    件    表") || cellValue.contains("配件名称")) {
                    JSONArray accessoriesTable = parseAccessoriesTable(sheet, rowIndex, cellIndex);
                    if (accessoriesTable != null && !accessoriesTable.isEmpty()) {
                        tableDataMap.put("accessoriesTable", accessoriesTable);
                    }
                    break;
                }
            }
        }
        
        return tableDataMap;
    }
    
    /**
     * 解析型材尺寸表
     *
     * @param sheet 工作表
     * @param startRowIndex 表格标题行索引
     * @param titleCellIndex 表格标题单元格索引
     * @return 表格数据的JSON数组
     */
    private JSONArray parseProfileSizeTable(Sheet sheet, int startRowIndex, int titleCellIndex) {
        JSONArray tableData = new JSONArray();
        
        // 查找表头行（通常在标题行的下一行或下两行）
        Row headerRow = null;
        int headerRowIndex = startRowIndex + 1;
        
        // 尝试找到包含列标题的行
        while (headerRowIndex <= sheet.getLastRowNum() && headerRowIndex <= startRowIndex + 5) {
            Row row = sheet.getRow(headerRowIndex);
            if (row != null && !isEmptyRow(row)) {
                // 检查该行是否包含列标题（如"序号"、"型材代码"等）
                boolean isHeaderRow = false;
                for (int i = 0; i < row.getLastCellNum(); i++) {
                    String cellValue = getCellValueAsString(row.getCell(i));
                    if (cellValue.contains("序号") || cellValue.contains("型材代码") || 
                        cellValue.contains("规格") || cellValue.contains("数量")) {
                        isHeaderRow = true;
                        break;
                    }
                }
                
                if (isHeaderRow) {
                    headerRow = row;
                    break;
                }
            }
            headerRowIndex++;
        }
        
        if (headerRow == null) {
            return tableData; // 没有找到表头行，返回空数组
        }
        
        // 使用titleCellIndex作为开始列
        int startCol = titleCellIndex;
        
        // 查找结束列 - 通过查找标题行中最后一个非空单元格
        int endCol = startCol + 8; // 增加列数以包含类别和备注
        
        // 提取列标题
        List<String> headers = new ArrayList<>();
        for (int i = startCol; i <= endCol; i++) {
            Cell cell = headerRow.getCell(i);
            if (cell != null) {
                headers.add(getCellValueAsString(cell));
            } else {
                headers.add(""); // 空列标题
            }
        }
        
        // 从表头行的下一行开始解析数据行
        int dataRowIndex = headerRowIndex + 1;
        while (dataRowIndex <= sheet.getLastRowNum()) {
            Row dataRow = sheet.getRow(dataRowIndex);
            if (dataRow == null) {
                dataRowIndex++;
                continue;
            }
            
            // 空行跳过
            if (isEmptyRow(dataRow)) {
                dataRowIndex++;
                continue;
            }
            
            // 检查是否到达表格末尾 - 如果当前行或下一行包含"总面积"，则结束解析
            boolean isEndOfProfileTable = false;
            Cell firstCell = dataRow.getCell(startCol);
            if (firstCell != null) {
                String cellValue = getCellValueAsString(firstCell);
                if (cellValue.contains("总面积")) {
                    isEndOfProfileTable = true;
                }
            }
            
            // 检查下一行是否包含"总面积"
            if (!isEndOfProfileTable && dataRowIndex + 1 <= sheet.getLastRowNum()) {
                Row nextRow = sheet.getRow(dataRowIndex + 1);
                if (nextRow != null) {
                    Cell nextFirstCell = nextRow.getCell(startCol);
                    if (nextFirstCell != null) {
                        String nextCellValue = getCellValueAsString(nextFirstCell);
                        if (nextCellValue.contains("总面积")) {
                            // 当前行是"总面积"的上一行，处理完当前行后结束
                            isEndOfProfileTable = true;
                        }
                    }
                }
            }
            
            // 解析数据行
            JSONObject rowData = new JSONObject();
            boolean hasData = false;
            
            // 查找类别和备注列的索引
            int categoryIndex = -1;
            int remarkIndex = -1;
            for (int i = 0; i < headers.size(); i++) {
                String header = headers.get(i);
                if (header.contains("类别")) {
                    categoryIndex = startCol + i;
                } else if (header.contains("备注")) {
                    remarkIndex = startCol + i;
                }
            }
            
            for (int i = 0; i < headers.size(); i++) {
                int colIndex = startCol + i;
                if (colIndex <= endCol) {
                    Cell cell = dataRow.getCell(colIndex);
                    if (cell != null && !isEmptyCell(cell)) {
                        String header = headers.get(i);
                        String value = getCellValueAsString(cell);
                        
                        if (!header.isEmpty() && !value.isEmpty()) {
                            rowData.put(header, value);
                            hasData = true;
                        }
                    }
                }
            }
            
            // 检查是否需要添加类别和备注
            if (categoryIndex >= 0) {
                Cell categoryCell = dataRow.getCell(categoryIndex);
                if (categoryCell != null && !isEmptyCell(categoryCell)) {
                    String categoryValue = getCellValueAsString(categoryCell);
                    rowData.put("类别", categoryValue);
                }
            }
            
            if (remarkIndex >= 0) {
                Cell remarkCell = dataRow.getCell(remarkIndex);
                if (remarkCell != null && !isEmptyCell(remarkCell)) {
                    String remarkValue = getCellValueAsString(remarkCell);
                    rowData.put("备注", remarkValue);
                }
            }
            
            // 只添加非空行
            if (hasData) {
                tableData.add(rowData);
            }
            
            // 如果到达表格末尾，结束解析
            if (isEndOfProfileTable) {
                break;
            }
            
            dataRowIndex++;
        }
        
        return tableData;
    }
    
    /**
     * 解析玻璃尺寸表
     *
     * @param sheet 工作表
     * @param startRowIndex 表格标题行索引
     * @param titleCellIndex 表格标题单元格索引
     * @return 表格数据的JSON数组
     */
    private JSONArray parseGlassSizeTable(Sheet sheet, int startRowIndex, int titleCellIndex) {
        JSONArray tableData = new JSONArray();
        
        // 查找表头行（通常在标题行的下一行或下两行）
        Row headerRow = null;
        int headerRowIndex = startRowIndex + 1;
        
        // 尝试找到包含列标题的行
        while (headerRowIndex <= sheet.getLastRowNum() && headerRowIndex <= startRowIndex + 5) {
            Row row = sheet.getRow(headerRowIndex);
            if (row != null && !isEmptyRow(row)) {
                // 检查该行是否包含列标题（如"序号"、"玻璃规格"等）
                boolean isHeaderRow = false;
                for (int i = 0; i < row.getLastCellNum(); i++) {
                    String cellValue = getCellValueAsString(row.getCell(i));
                    if (cellValue.contains("序号") || cellValue.contains("玻璃规格") || 
                        cellValue.contains("数量") || cellValue.contains("玻璃类型")) {
                        isHeaderRow = true;
                        break;
                    }
                }
                
                if (isHeaderRow) {
                    headerRow = row;
                    break;
                }
            }
            headerRowIndex++;
        }
        
        if (headerRow == null) {
            return tableData; // 没有找到表头行，返回空数组
        }
        // 使用titleCellIndex作为开始列
        int startCol = titleCellIndex;

        // 查找结束列 - 通过查找标题行中最后一个非空单元格
        int endCol = startCol + 5;
        
        // 提取列标题
        List<String> headers = new ArrayList<>();
        for (int i = startCol; i <= endCol; i++) {
            Cell cell = headerRow.getCell(i);
            if (cell != null) {
                headers.add(getCellValueAsString(cell));
            } else {
                headers.add(""); // 空列标题
            }
        }
        
        // 从表头行的下一行开始解析数据行
        int dataRowIndex = headerRowIndex + 1;
        while (dataRowIndex <= sheet.getLastRowNum()) {
            Row dataRow = sheet.getRow(dataRowIndex);
            if (dataRow == null) {
                dataRowIndex++;
                continue;
            }
            
            // 空行跳过
            if (isEmptyRow(dataRow)) {
                dataRowIndex++;
                continue;
            }
            
            // 检查是否到达表格末尾 - 如果当前行或下一行包含"配件表"，则结束解析
            boolean isEndOfGlassTable = false;
            
            // 检查当前行是否包含"配件表"
            for (int i = 0; i < dataRow.getLastCellNum(); i++) {
                Cell cell = dataRow.getCell(i);
                if (cell != null) {
                    String cellValue = getCellValueAsString(cell);
                    if (cellValue.contains("内 扇 尺 寸 表") || cellValue.contains("内扇尺寸表")) {
                        // 当前行包含配件表标题，不处理当前行
                        isEndOfGlassTable = true;
                        break;
                    }
                }
            }
            
            // 检查下一行是否包含"配件表"
            if (!isEndOfGlassTable && dataRowIndex + 1 <= sheet.getLastRowNum()) {
                Row nextRow = sheet.getRow(dataRowIndex);
                if (nextRow != null) {
                    for (int i = 0; i < nextRow.getLastCellNum(); i++) {
                        Cell cell = nextRow.getCell(i);
                        if (cell != null) {
                            String cellValue = getCellValueAsString(cell);
                            if (cellValue.contains("配件表") || cellValue.contains("配    件    表")) {
                                // 下一行包含配件表标题，处理完当前行后结束
                                isEndOfGlassTable = true;
                                break;
                            }
                        }
                    }
                }
            }
            
            // 如果遇到配件表标题行，结束解析
            if (isEndOfGlassTable) {
                break;
            }
            
            // 解析数据行
            JSONObject rowData = new JSONObject();
            boolean hasData = false;
            
            for (int i = 0; i < headers.size(); i++) {
                int colIndex = startCol + i;
                if (colIndex <= endCol) {
                    Cell cell = dataRow.getCell(colIndex);
                    if (cell != null && !isEmptyCell(cell)) {
                        String header = headers.get(i);
                        String value = getCellValueAsString(cell);
                        
                        if (!header.isEmpty() && !value.isEmpty()) {
                            rowData.put(header, value);
                            hasData = true;
                        }
                    }
                }
            }
            
            // 只添加非空行
            if (hasData) {
                tableData.add(rowData);
            }
            
            dataRowIndex++;
        }
        
        return tableData;
    }
    
    /**
     * 解析配件表
     *
     * @param sheet 工作表
     * @param startRowIndex 表格标题行索引
     * @param titleCellIndex 表格标题单元格索引
     * @return 表格数据的JSON数组
     */
    private JSONArray parseAccessoriesTable(Sheet sheet, int startRowIndex, int titleCellIndex) {
        JSONArray tableData = new JSONArray();
        
        // 查找表头行（通常在标题行的下一行或下两行）
        Row headerRow = null;
        int headerRowIndex = startRowIndex + 1;
        
        // 尝试找到包含列标题的行
        while (headerRowIndex <= sheet.getLastRowNum() && headerRowIndex <= startRowIndex + 5) {
            Row row = sheet.getRow(headerRowIndex);
            if (row != null && !isEmptyRow(row)) {
                // 检查该行是否包含列标题
                boolean isHeaderRow = false;
                for (int i = 0; i < row.getLastCellNum(); i++) {
                    String cellValue = getCellValueAsString(row.getCell(i));
                    if (cellValue.contains("序号") || cellValue.contains("配件名称") || 
                        cellValue.contains("规格") || cellValue.contains("数量") ||
                        cellValue.contains("单位") || cellValue.contains("品牌")) {
                        isHeaderRow = true;
                        break;
                    }
                }
                
                if (isHeaderRow) {
                    headerRow = row;
                    break;
                }
            }
            headerRowIndex++;
        }
        
        if (headerRow == null) {
            return tableData; // 没有找到表头行，返回空数组
        }
        
        // 使用titleCellIndex作为基础开始列
        int baseStartCol = titleCellIndex;
        
        // 配件表特殊处理：查找所有"配件名称"列和对应的"品牌"列
        List<Integer> partStartCols = new ArrayList<>();
        List<Integer> partEndCols = new ArrayList<>();
        
        // 先找到所有可能的配件名称列
        for (int i = 0; i < headerRow.getLastCellNum(); i++) {
            Cell cell = headerRow.getCell(i);
            if (cell != null) {
                String cellValue = getCellValueAsString(cell);
                if (cellValue.contains("配件名称") || cellValue.contains("序号")) {
                    // 确保起始列不小于基础开始列
                    if (i >= baseStartCol) {
                        partStartCols.add(i);
                    }
                }
            }
        }
        
        // 如果没有找到配件名称列，使用基础开始列
        if (partStartCols.isEmpty()) {
            partStartCols.add(baseStartCol);
        }
        
        // 查找每个部分的结束列
        for (int partIndex = 0; partIndex < partStartCols.size(); partIndex++) {
            int partStartCol = partStartCols.get(partIndex);
            int partEndCol = headerRow.getLastCellNum() - 1; // 默认到行尾
            
            // 查找当前部分的结束列（通常是品牌列）
            for (int i = partStartCol; i < headerRow.getLastCellNum(); i++) {
                Cell cell = headerRow.getCell(i);
                if (cell != null) {
                    String cellValue = getCellValueAsString(cell);
                    if (cellValue.contains("品牌")) {
                        // 找到了品牌列，设置为当前部分的结束列
                        partEndCol = i;
                        partEndCols.add(partEndCol);
                        break;
                    }
                }
            }
            
            // 如果没有找到品牌列，检查是否有下一个配件名称列
            if (partEndCols.size() <= partIndex) {
                if (partIndex + 1 < partStartCols.size()) {
                    // 使用下一个配件名称列的前一列作为结束列
                    partEndCol = partStartCols.get(partIndex + 1) - 1;
                }
                partEndCols.add(partEndCol);
            }
        }
        
        // 处理每一部分（左右两部分）
        for (int partIndex = 0; partIndex < partStartCols.size(); partIndex++) {
            int partStartCol = partStartCols.get(partIndex);
            int partEndCol = partEndCols.get(partIndex);
            
            // 提取该部分的列标题
            List<String> headers = new ArrayList<>();
            for (int i = partStartCol; i <= partEndCol; i++) {
                Cell cell = headerRow.getCell(i);
                if (cell != null) {
                    headers.add(getCellValueAsString(cell));
                } else {
                    headers.add(""); // 空列标题
                }
            }
            
            // 从表头行的下一行开始解析数据行
            int dataRowIndex = headerRowIndex + 1;
            while (dataRowIndex <= sheet.getLastRowNum()) {
                Row dataRow = sheet.getRow(dataRowIndex);
                if (dataRow == null) {
                    dataRowIndex++;
                    continue;
                }
                
                // 空行跳过
                if (isEmptyRow(dataRow)) {
                    dataRowIndex++;
                    continue;
                }
                
                // 检查下一行的第一列是否包含"订单名称"
                boolean isEndOfAccessoriesTable = false;
                if (dataRowIndex + 1 <= sheet.getLastRowNum()) {
                    Row nextRow = sheet.getRow(dataRowIndex + 1);
                    if (nextRow != null) {
                        Cell firstCell = nextRow.getCell(0);
                        if (firstCell != null) {
                            String cellValue = getCellValueAsString(firstCell);
                            if (cellValue.contains("订单名称")) {
                                // 下一行包含订单名称，处理完当前行后结束
                                isEndOfAccessoriesTable = true;
                            }
                        }
                    }
                }
                
                // 解析数据行
                JSONObject rowData = new JSONObject();
                boolean hasData = false;
                
                for (int i = 0; i < headers.size(); i++) {
                    int colIndex = partStartCol + i;
                    if (colIndex <= partEndCol) {
                        Cell cell = dataRow.getCell(colIndex);
                        if (cell != null && !isEmptyCell(cell)) {
                            String header = headers.get(i);
                            String value = getCellValueAsString(cell);
                            
                            if (!header.isEmpty() && !value.isEmpty()) {
                                rowData.put(header, value);
                                hasData = true;
                            }
                        }
                    }
                }
                
                // 只添加非空行
                if (hasData) {
                    // 添加一个标识，表示这是第几部分的数据
                    rowData.put("partIndex", partIndex + 1);
                    tableData.add(rowData);
                }
                
                // 如果下一行包含订单名称，结束解析
                if (isEndOfAccessoriesTable) {
                    break;
                }
                
                dataRowIndex++;
            }
            
            // 如果已经到达表格末尾（发现了订单名称），则不再处理其他部分
            if (dataRowIndex > sheet.getLastRowNum() || 
                (dataRowIndex + 1 <= sheet.getLastRowNum() && 
                 sheet.getRow(dataRowIndex + 1) != null && 
                 sheet.getRow(dataRowIndex + 1).getCell(0) != null && 
                 getCellValueAsString(sheet.getRow(dataRowIndex + 1).getCell(0)).contains("订单名称"))) {
                break;
            }
        }
        
        return tableData;
    }
    
    /**
     * 判断是否到达表格末尾
     * 
     * @param row 当前行
     * @param startCol 表格开始列
     * @return 是否到达表格末尾
     */
    private boolean isEndOfTable(Row row, int startCol) {
        // 检查是否是空行
        if (isEmptyRow(row)) {
            return true;
        }
        
        // 检查是否包含"合计"、"总计"等表格结束标记
        Cell firstCell = row.getCell(startCol);
        if (firstCell != null) {
            String cellValue = getCellValueAsString(firstCell);
            if (cellValue.contains("合计") || cellValue.contains("总计")) {
                return true;
            }
        }
        
        // 检查连续两行是否为空，如果是则认为到达表格末尾
        if (row.getRowNum() + 1 <= row.getSheet().getLastRowNum()) {
            Row nextRow = row.getSheet().getRow(row.getRowNum() + 1);
            if (nextRow == null || isEmptyRow(nextRow)) {
                Row nextNextRow = row.getSheet().getRow(row.getRowNum() + 2);
                if (nextNextRow == null || isEmptyRow(nextNextRow)) {
                    return true;
                }
            }
        }
        
        return false;
    }
    
    /**
     * 判断行是否为空
     *
     * @param row 行
     * @return 是否为空行
     */
    private boolean isEmptyRow(Row row) {
        if (row == null) {
            return true;
        }
        
        for (int i = 0; i < row.getLastCellNum(); i++) {
            Cell cell = row.getCell(i);
            if (!isEmptyCell(cell)) {
                return false;
            }
        }
        
        return true;
    }
    
    /**
     * 创建产品明细对象
     *
     * @param windowInfo 窗型基本信息
     * @param tableDataMap 表格数据映射
     * @param sheet 工作表
     * @param section 窗型区域
     * @param workbook 工作簿
     * @param tenantId 租户ID
     * @return 产品销售订单明细对象
     */
    private ProductSalesOrderDetail createProductDetail(Map<String, String> windowInfo, Map<String, JSONArray> tableDataMap,
                                                      Sheet sheet, WindowSection section, Workbook workbook, Integer tenantId) {
        // 提取窗型图片
        String imagePath = extractAndSaveImage(sheet, section.getStartRow(), section.getEndRow(), windowInfo, workbook);
        
        // 创建产品明细对象
        ProductSalesOrderDetail detail = new ProductSalesOrderDetail();
        detail.setId(UUID.randomUUID().toString().replace("-", ""));
        
        // 设置租户ID
        detail.setTenantId(tenantId);
        
        // 设置窗号
        String windowNo = windowInfo.get("windowNo");
        if (windowNo != null) {
            detail.setWindowNo(windowNo);
        } else {
            detail.setWindowNo("未知窗号");
        }
        
        // 设置门窗系列
        String windowSeries = windowInfo.get("windowSeries");
        if (windowSeries != null) {
            detail.setWindowSeries(windowSeries);
        }
        
        // 设置数量
        String quantity = windowInfo.get("quantity");
        if (quantity != null) {
            try {
                detail.setQuantity(Integer.parseInt(quantity));
            } catch (NumberFormatException e) {
                detail.setQuantity(1); // 默认数量为1
            }
        } else {
            detail.setQuantity(1); // 默认数量为1
        }
        
        // 设置颜色
        String color = windowInfo.get("color");
        if (color != null) {
            detail.setWindowColor(color);
        }
        
        // 设置总面积
        String totalArea = windowInfo.get("totalArea");
        if (totalArea != null) {
            try {
                detail.setTotalArea(new BigDecimal(totalArea.replaceAll("[^\\d.]", "")));
            } catch (Exception e) {
                // 解析失败，不设置该字段
            }
        }
        
        // 设置总重量
        String totalWeight = windowInfo.get("totalWeight");
        if (totalWeight != null) {
            try {
                detail.setTotalWeight(new BigDecimal(totalWeight.replaceAll("[^\\d.]", "")));
            } catch (Exception e) {
                // 解析失败，不设置该字段
            }
        }
        
        // 设置单窗面积
        String singleWindowArea = windowInfo.get("singleWindowArea");
        if (singleWindowArea != null) {
            try {
                detail.setSingleWindowArea(new BigDecimal(singleWindowArea.replaceAll("[^\\d.]", "")));
            } catch (Exception e) {
                // 解析失败，不设置该字段
            }
        }
        
        // 设置单窗重量
        String singleWindowWeight = windowInfo.get("singleWindowWeight");
        if (singleWindowWeight != null) {
            try {
                detail.setSingleWindowWeight(new BigDecimal(singleWindowWeight.replaceAll("[^\\d.]", "")));
            } catch (Exception e) {
                // 解析失败，不设置该字段
            }
        }
        
        // 设置技术要求
        String technicalRequirements = windowInfo.get("technicalRequirements");
        if (technicalRequirements != null) {
            detail.setTechnicalRequirements(technicalRequirements);
        }
        
        // 设置安装位置
        String installationLocation = windowInfo.get("installationLocation");
        if (installationLocation != null) {
            detail.setInstallationLocation(installationLocation);
        }
        
        // 设置表格数据
        if (tableDataMap.containsKey("profileSizeTable")) {
            detail.setProfileSizeTableJson(tableDataMap.get("profileSizeTable").toJSONString());
        }
        
        if (tableDataMap.containsKey("glassSizeTable")) {
            detail.setGlassSizeTableJson(tableDataMap.get("glassSizeTable").toJSONString());
        }
        
        if (tableDataMap.containsKey("accessoriesTable")) {
            detail.setAccessoriesTableJson(tableDataMap.get("accessoriesTable").toJSONString());
        }

        // 设置合同编号
        String contractNo = windowInfo.get("contractNo");
        if (contractNo != null) {
            detail.setOrderId(contractNo);
        }
        
        // 设置图片路径
        if (imagePath != null) {
            detail.setPhotoUrl(imagePath);
            // 不再设置drawingFile字段
            // detail.setDrawingFile(imagePath);
        } else {
            // 当没有图片时，将photoUrl设置为null
            detail.setPhotoUrl(null);
            System.out.println("未找到图片，设置photoUrl为null");
        }
        
        // 将窗型信息添加到extendMap中，以便Controller能够获取
        Map<String, Object> extendMap = new HashMap<>();
        extendMap.put("windowInfo", windowInfo);
        detail.setExtendMap(extendMap);
        
        return detail;
    }
    
    /**
     * 提取并保存窗型图片
     * 
     * @param sheet 工作表
     * @param startRow 起始行
     * @param endRow 结束行
     * @param windowInfo 窗型基本信息
     * @param workbook 工作簿
     * @return 保存的图片路径
     */
    private String extractAndSaveImage(Sheet sheet, int startRow, int endRow, Map<String, String> windowInfo, Workbook workbook) {
        // 提取图片可能需要使用POI的特定API
        
        String contractNo = windowInfo.get("contractNo");
        String windowNo = windowInfo.get("windowNo");
        String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
        
        System.out.println("开始提取窗号 " + windowNo + " 的图片，行范围: " + startRow + " - " + endRow);
        
        // 图片文件名格式：订单编号+窗号+时间戳
        String imageFileName = (contractNo != null ? contractNo : "unknown") + "_" 
                             + (windowNo != null ? windowNo : "unknown") + "_" 
                             + timestamp + ".png";
        
        // 图片保存路径 - 使用windowImages目录，与Controller中保持一致
        String bizPath = "windowImages";
        String saveDir = uploadPath + File.separator + bizPath;
        File dir = new File(saveDir);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        
        String imagePath = null;
        
        try {
            // 尝试从当前工作表中提取图片，而不是从整个工作簿
            List<PictureData> pictures = new ArrayList<>();
            Map<Integer, PictureData> pictureMap = new HashMap<>(); // 用于记录图片与其在工作表中的位置关系
            
            // 获取工作表中的所有绘图对象
            Drawing<?> drawing = sheet.getDrawingPatriarch();
            if (drawing != null) {
                System.out.println("工作表中存在绘图对象");
                
                // 遍历所有图片，查找位于当前窗型区域内的图片
                int pictureCount = 0;
                for (org.apache.poi.ss.usermodel.Shape shape : drawing) {
                    if (shape instanceof org.apache.poi.ss.usermodel.Picture) {
                        pictureCount++;
                        org.apache.poi.ss.usermodel.Picture pic = (org.apache.poi.ss.usermodel.Picture) shape;
                        org.apache.poi.ss.usermodel.ClientAnchor anchor = pic.getClientAnchor();
                        
                        if (anchor != null) {
                            System.out.println("图片 " + pictureCount + " 位置: 行" + anchor.getRow1() + "-" + anchor.getRow2() + 
                                             ", 列" + anchor.getCol1() + "-" + anchor.getCol2());
                            
                            // 检查图片是否在当前窗型的行范围内或接近范围
                            // 有时图片可能稍微超出窗型区域，所以我们允许一定的容差
                            int tolerance = 10; // 允许的行数容差
                            if ((anchor.getRow1() >= startRow - tolerance && anchor.getRow1() <= endRow + tolerance) || 
                                (anchor.getRow2() >= startRow - tolerance && anchor.getRow2() <= endRow + tolerance)) {
                                
                                pictures.add(pic.getPictureData());
                                // 记录图片与其在工作表中的位置关系，使用行号作为键
                                pictureMap.put(anchor.getRow1(), pic.getPictureData());
                                
                                System.out.println("找到位于窗型区域内的图片: 行" + anchor.getRow1() + "-" + anchor.getRow2());
                            }
                        }
                    }
                }
                
                System.out.println("工作表中共有 " + pictureCount + " 个图片，其中 " + pictures.size() + " 个位于当前窗型区域内");
            } else {
                System.out.println("工作表中不存在绘图对象，无法直接获取图片位置信息");
            }
            
            // 如果在当前区域找到了多张图片，尝试选择最合适的一张
            if (pictures.size() > 1) {
                System.out.println("在窗型区域内找到多张图片，尝试选择最合适的一张");
                
                // 查找最接近窗型开始行的图片
                PictureData bestMatch = null;
                int minDistance = Integer.MAX_VALUE;
                
                for (Map.Entry<Integer, PictureData> entry : pictureMap.entrySet()) {
                    int rowPosition = entry.getKey();
                    int distance = Math.abs(rowPosition - startRow);
                    
                    if (distance < minDistance) {
                        minDistance = distance;
                        bestMatch = entry.getValue();
                    }
                }
                
                if (bestMatch != null) {
                    // 清空列表并添加最佳匹配的图片
                    pictures.clear();
                    pictures.add(bestMatch);
                    System.out.println("选择了距离窗型开始行最近的图片，距离为 " + minDistance + " 行");
                }
            }
            
            // 如果在当前区域没有找到图片，则尝试从整个工作簿中查找
            if (pictures.isEmpty()) {
                System.out.println("在窗型区域(" + startRow + "-" + endRow + ")内未找到图片，尝试从整个工作簿中查找");
                
                // 获取工作簿中的所有图片
                List<? extends PictureData> allPictures = workbook.getAllPictures();
                System.out.println("工作簿中共有 " + allPictures.size() + " 张图片");
                
                if (!allPictures.isEmpty()) {
                    // 如果工作簿中的图片数量与窗型区域数量相同，则可能是一一对应的关系
                    // 尝试根据窗型在工作表中的顺序来匹配图片
                    int sectionIndex = -1;
                    List<WindowSection> allSections = divideSheetIntoWindowSections(sheet);
                    
                    for (int i = 0; i < allSections.size(); i++) {
                        WindowSection section = allSections.get(i);
                        if (section.getStartRow() == startRow && section.getEndRow() == endRow) {
                            sectionIndex = i;
                            break;
                        }
                    }
                    
                    if (sectionIndex >= 0 && sectionIndex < allPictures.size()) {
                        pictures.add(allPictures.get(sectionIndex));
                        System.out.println("根据窗型顺序匹配图片，当前窗型索引: " + sectionIndex);
                    } else {
                        // 如果无法根据顺序匹配，则使用第一张图片
                        pictures.add(allPictures.get(0));
                        System.out.println("无法根据窗型顺序匹配图片，使用第一张图片");
                    }
                }
            }
            
            // 保存找到的图片
            if (!pictures.isEmpty()) {
                // 使用找到的第一张图片
                PictureData picture = pictures.get(0);
                byte[] data = picture.getData();
                
                // 保存图片
                String filePath = saveDir + File.separator + imageFileName;
                try (OutputStream out = new FileOutputStream(filePath)) {
                    out.write(data);
                }
                
                // 返回相对路径，使用与Controller中一致的格式
                imagePath = bizPath + "/" + imageFileName;
                
                // 记录日志
                System.out.println("成功提取并保存图片: " + imagePath + " 用于窗号: " + windowNo);
            } else {
                System.out.println("未找到任何图片用于窗号: " + windowNo);
            }
        } catch (Exception e) {
            // 图片提取失败，记录日志但不影响解析
            System.err.println("提取图片失败: " + e.getMessage());
            e.printStackTrace();
        }
        
        return imagePath;
    }
    
    /**
     * 从行中提取关键信息
     * 
     * @param row 当前行
     * @param windowInfo 窗型信息映射
     */
    private void extractKeyInfo(Row row, Map<String, String> windowInfo) {
        if (row == null || row.getLastCellNum() <= 0) {
            return;
        }
        
        // 遍历行中的所有单元格，查找关键信息
        for (int cellIndex = 0; cellIndex < row.getLastCellNum(); cellIndex++) {
            Cell cell = row.getCell(cellIndex);
            if (cell == null) {
                continue;
            }
            
            String cellValue = getCellValueAsString(cell);
            if (cellValue.isEmpty()) {
                continue;
            }
            
            // 提取门窗系列
            if (cellValue.contains("门窗系列")) {
                // 检查当前单元格右侧是否有值
                Cell nextCell = row.getCell(cellIndex + 1);
                if (nextCell != null && !isEmptyCell(nextCell)) {
                    windowInfo.put("windowSeries", getCellValueAsString(nextCell));
                } else {
                    // 检查下一行相同位置是否有值
                    Row nextRow = row.getSheet().getRow(row.getRowNum() + 1);
                    if (nextRow != null) {
                        Cell valueCell = nextRow.getCell(cellIndex);
                        if (valueCell != null && !isEmptyCell(valueCell)) {
                            windowInfo.put("windowSeries", getCellValueAsString(valueCell));
                        }
                    }
                }
            }
            
            // 提取门窗代号（窗号）
            else if (cellValue.contains("门窗代号") || cellValue.contains("门窗编号")) {
                // 检查下一行相同位置是否有值
                Row nextRow = row.getSheet().getRow(row.getRowNum() + 1);
                if (nextRow != null) {
                    Cell valueCell = nextRow.getCell(cellIndex);
                    if (valueCell != null && !isEmptyCell(valueCell)) {
                        windowInfo.put("windowNo", getCellValueAsString(valueCell));
                    }
                }
            }
            
            // 提取数量
            else if (cellValue.contains("数量") &&  getCellValueAsString(row.getCell(cellIndex-2)).equals("门窗代号")) {
                // 检查下一行相同位置是否有值
                Row nextRow = row.getSheet().getRow(row.getRowNum() + 1);
                if (nextRow != null) {
                    Cell valueCell = nextRow.getCell(cellIndex);
                    if (valueCell != null && !isEmptyCell(valueCell)) {
                        windowInfo.put("quantity", getCellValueAsString(valueCell));
                    }
                }
            }
            
            // 提取颜色
            else if (cellValue.contains("颜色")) {
                // 检查下一行相同位置是否有值
                Row nextRow = row.getSheet().getRow(row.getRowNum() + 1);
                if (nextRow != null) {
                    Cell valueCell = nextRow.getCell(cellIndex);
                    if (valueCell != null && !isEmptyCell(valueCell)) {
                        windowInfo.put("color", getCellValueAsString(valueCell));
                    }
                }
            }
            
            // 提取外形尺寸
            else if (cellValue.contains("外形尺寸") || cellValue.contains("外框尺寸")) {
                // 检查下一行相同位置是否有值
                Row nextRow = row.getSheet().getRow(row.getRowNum() + 1);
                if (nextRow != null) {
                    Cell valueCell = nextRow.getCell(cellIndex);
                    if (valueCell != null && !isEmptyCell(valueCell)) {
                        windowInfo.put("size", getCellValueAsString(valueCell));
                    }
                }
            }
            
            // 提取合同编号
            else if (cellValue.contains("合同编号")) {
                Cell nextCell = row.getCell(cellIndex + 1);
                if (nextCell != null) {
                    windowInfo.put("contractNo", getCellValueAsString(nextCell));
                }
            }
            
            // 提取下单日期
            else if (cellValue.contains("下单日期")) {
                Cell nextCell = row.getCell(cellIndex + 1);
                if (nextCell != null) {
                    windowInfo.put("orderDate", getCellValueAsString(nextCell));
                }
            }
            
            // 提取完工日期
            else if (cellValue.contains("完工日期")) {
                Cell nextCell = row.getCell(cellIndex + 1);
                if (nextCell != null) {
                    windowInfo.put("completionDate", getCellValueAsString(nextCell));
                }
            }
            
            // 提取总面积
            else if (cellValue.contains("总面积")) {
                Cell nextCell = row.getCell(cellIndex + 2);
                if (nextCell != null) {
                    windowInfo.put("totalArea", getCellValueAsString(nextCell));
                }
            }
            
            // 提取总重量
            else if (cellValue.contains("总重量")) {
                Cell nextCell = row.getCell(cellIndex + 2);
                if (nextCell != null) {
                    windowInfo.put("totalWeight", getCellValueAsString(nextCell));
                }
            }
            
            // 提取单窗面积
            else if (cellValue.contains("单窗面积")) {
                Cell nextCell = row.getCell(cellIndex + 2);
                if (nextCell != null) {
                    windowInfo.put("singleWindowArea", getCellValueAsString(nextCell));
                }
            }
            
            // 提取单窗重量
            else if (cellValue.contains("单窗重量")) {
                Cell nextCell = row.getCell(cellIndex + 2);
                if (nextCell != null) {
                    windowInfo.put("singleWindowWeight", getCellValueAsString(nextCell));
                }
            }
            
            // 提取技术要求
            else if (cellValue.contains("技术要求")) {
                // 检查当前单元格右侧是否有值
                Cell nextCell = row.getCell(cellIndex + 1);
                if (nextCell != null && !isEmptyCell(nextCell)) {
                    windowInfo.put("technicalRequirements", getCellValueAsString(nextCell));
                } else {
                    // 检查下一行相同位置是否有值
                    Row nextRow = row.getSheet().getRow(row.getRowNum() + 1);
                    if (nextRow != null) {
                        Cell valueCell = nextRow.getCell(cellIndex);
                        if (valueCell != null && !isEmptyCell(valueCell)) {
                            windowInfo.put("technicalRequirements", getCellValueAsString(valueCell));
                        }
                    }
                }
            }
            
            // 提取安装位置
            else if (cellValue.contains("安装位置")) {
                // 检查当前单元格右侧是否有值
                Cell nextCell = row.getCell(cellIndex + 1);
                if (nextCell != null && !isEmptyCell(nextCell)) {
                    windowInfo.put("installationLocation", getCellValueAsString(nextCell));
                } else {
                    // 检查下一行相同位置是否有值
                    Row nextRow = row.getSheet().getRow(row.getRowNum() + 1);
                    if (nextRow != null) {
                        Cell valueCell = nextRow.getCell(cellIndex);
                        if (valueCell != null && !isEmptyCell(valueCell)) {
                            windowInfo.put("installationLocation", getCellValueAsString(valueCell));
                        }
                    }
                }
            }
            
            // 从表格标题行直接提取信息
            // 根据您分享的表格图片，很多信息直接在表格的标题行
//            else if (cellValue.equals("门窗代号") || cellValue.equals("门窗编号")) {
//                // 检查下一行是否有窗号值
//                Row dataRow = row.getSheet().getRow(row.getRowNum() + 1);
//                if (dataRow != null) {
//                    Cell valueCell = dataRow.getCell(cellIndex);
//                    if (valueCell != null && !isEmptyCell(valueCell)) {
//                        windowInfo.put("windowNo", getCellValueAsString(valueCell));
//                    }
//                }
//            }
//            else if (cellValue.equals("数量")) {
//                // 检查下一行是否有数量值
//                Row dataRow = row.getSheet().getRow(row.getRowNum() + 1);
//                if (dataRow != null) {
//                    Cell valueCell = dataRow.getCell(cellIndex);
//                    if (valueCell != null && !isEmptyCell(valueCell)) {
//                        windowInfo.put("quantity", getCellValueAsString(valueCell));
//                    }
//                }
//            }
//            else if (cellValue.equals("颜色")) {
//                // 检查下一行是否有颜色值
//                Row dataRow = row.getSheet().getRow(row.getRowNum() + 1);
//                if (dataRow != null) {
//                    Cell valueCell = dataRow.getCell(cellIndex);
//                    if (valueCell != null && !isEmptyCell(valueCell)) {
//                        windowInfo.put("color", getCellValueAsString(valueCell));
//                    }
//                }
//            }
//            else if (cellValue.equals("外形尺寸") || cellValue.equals("外框尺寸")) {
//                // 检查下一行是否有尺寸值
//                Row dataRow = row.getSheet().getRow(row.getRowNum() + 1);
//                if (dataRow != null) {
//                    Cell valueCell = dataRow.getCell(cellIndex);
//                    if (valueCell != null && !isEmptyCell(valueCell)) {
//                        windowInfo.put("size", getCellValueAsString(valueCell));
//                    }
//                }
//            }
//            else if (cellValue.equals("门窗系列")) {
//                // 检查下一行是否有门窗系列值
//                Row dataRow = row.getSheet().getRow(row.getRowNum() + 1);
//                if (dataRow != null) {
//                    Cell valueCell = dataRow.getCell(cellIndex);
//                    if (valueCell != null && !isEmptyCell(valueCell)) {
//                        windowInfo.put("windowSeries", getCellValueAsString(valueCell));
//                    }
//                }
//            }
        }
    }
    
    /**
     * 判断是否是窗型分隔行
     *
     * @param row 行
     * @return 是否是分隔行
     */
    private boolean isWindowDividerRow(Row row) {
        Cell firstCell = row.getCell(0);
        if (firstCell == null) {
            return false;
        }
        
        String cellValue = getCellValueAsString(firstCell);
        for (String keyword : WINDOW_DIVIDER_KEYWORDS) {
            if (cellValue.contains(keyword)) {
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * 判断单元格是否为空
     *
     * @param cell 单元格
     * @return 是否为空
     */
    private boolean isEmptyCell(Cell cell) {
        return cell == null || cell.getCellType() == CellType.BLANK || 
               (cell.getCellType() == CellType.STRING && cell.getStringCellValue().trim().isEmpty());
    }
    
    /**
     * 获取单元格的字符串值
     *
     * @param cell 单元格
     * @return 字符串值
     */
    private String getCellValueAsString(Cell cell) {
        if (cell == null) {
            return "";
        }
        
        switch (cell.getCellType()) {
            case STRING:
                return cell.getStringCellValue().trim();
            case NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)) {
                    return cell.getDateCellValue().toString();
                } else {
                    // 避免数值显示为科学计数法
                    long longValue = (long) cell.getNumericCellValue();
                    if (longValue == cell.getNumericCellValue()) {
                        return String.valueOf(longValue);
                    } else {
                        return String.valueOf(cell.getNumericCellValue());
                    }
                }
            case BOOLEAN:
                return String.valueOf(cell.getBooleanCellValue());
            case FORMULA:
                try {
                    double numericValue = cell.getNumericCellValue();
                    long longValue = (long) numericValue;
                    if (longValue == numericValue) {
                        return String.valueOf(longValue);
                    } else {
                        return String.valueOf(numericValue);
                    }
                } catch (Exception e) {
                    try {
                        return cell.getStringCellValue();
                    } catch (Exception ex) {
                        return "";
                    }
                }
            default:
                return "";
        }
    }
} 